package com.java.java8.func.parallelstream;

import lombok.val;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class TestDemo
{
  private static List<Integer> list1 = new ArrayList<>();
  private static List<Integer> list2 = new ArrayList<>();

  public static void main(String[] args)
  {
    val task = IntStream.range(0, 10)
      .mapToObj(RyzeTask::new)
      .collect(Collectors.toList());

    IntStream.range(0, 10000)
      .forEach(list1::add);

    IntStream.range(0, 10000).parallel()
      .forEach(list2::add);

    System.out.println("串行执行的大小：" + list1.size());
    System.out.println("并行执行的大小：" + list2.size());

//    run1(task);
    run2(task);
//    run3(task);

  }

  //主线程顺序执行
  public static void run1(final List<RyzeTask> tasks)
  {
    val start  = System.nanoTime();
    val result = tasks.stream()
                   .map(RyzeTask::calculate)
                   .collect(Collectors.toList());
    val time   = (System.nanoTime() - start) / 1_000_000;

    System.out.printf("处理 %d任务花费 %d millis\n", tasks.size(), time);
    System.out.println(result);
  }

  //Java8并行Stream
  public static void run2(final List<RyzeTask> tasks)
  {
    val start  = System.nanoTime();
    val result = tasks.parallelStream()
                   .map(RyzeTask::calculate)
                   .collect(Collectors.toList());
    val time   = (System.nanoTime() - start) / 1_000_000;

    System.out.printf("处理 %d任务花费 %d millis\n", tasks.size(), time);
    System.out.println(result);
  }

  //Java8异步
  public static void run3(List<RyzeTask> tasks)
  {
    val start    = System.nanoTime();
    val executor = Executors.newFixedThreadPool(10);

    val futures  = tasks.stream()
                    .map(t -> CompletableFuture.supplyAsync(() -> t.calculate(), executor))
                    .collect(Collectors.toList());
    val result   = futures.stream()
                   .map(CompletableFuture::join)
                   .collect(Collectors.toList());

    val time     = (System.nanoTime() - start) / 1_000_000;

    System.out.printf("处理 %d 任务花费 %d millis\n", tasks.size(), time);
    System.out.println(result);
  }

}

class RyzeTask
{
  public final int time;

  public RyzeTask(final int time)
  {
    this.time = time;
  }

  public int calculate()
  {
    System.out.println("当前线程名 =====> " + Thread.currentThread().getName());
    try
    {
      Thread.sleep(time * 1000);
    }
    catch (Exception e)
    {
      throw new RuntimeException(e);
    }

    return time;
  }
}